"""
My command module template

"""

from ev import Command as BaseCommand
from ev import default_cmds, utils


class MyCommand(BaseCommand):
    """
    Command class to handle my custom commands that deal 
    with more that one result (eg. get sword.2, get sword.all
    to get respectively the second sword and all swords).

    """

    def parse(self):
        """
        Inherit from this to make commands to interact with one
        or more objects (get, put, move etc.).
        This parser get args and trys to search objects with the 
        corresponding criteria, it supports:

          <name> - to get the first objects found
          all - to get all objects in the location and caller's inventory
          <name>.all - to get all objects found with the search query
          <name>.<number> - to get one specific object

       Only supports aliases, to search objects by object name you can use 
       underscore instead of space ("A_knife" it's ok but not "A knife")

       It returns self.targets_one, a list of objects to interact with,
       and self.index, the index number of the selected one.
          
        """

        if not self.args:
            return
        caller = self.caller;
        args = self.args.strip().split()

        # to search objects by object name you can use underscore instead of space
        args = [element.strip().replace("_", " ") for element in args]
        args = [self.at_multimatch_input(element) for element in args]
        self.args = args



    def get_objects_from_string(self, index, string, location, n=1):
        """
        Use this function with an index and a string defining an ingame-object.
        This is almost like object_search but can understand index numbers of objects
        with the same name and could restrains results to obj.contents only.
        Useful to the func() method of commands. Returns always a list.
        
        index = the index number of the object we want to get

        string = the string defining the object

        candidates = list of objects limiting the search

        """
        caller = self.caller
        if not string.strip(): return []
        if not location: return []
        if string == 'all':
           list_ = []
           for element in utils.make_iter(location):
               list_.extend(element.contents)
           return filter(lambda x: (hasattr(x, "wild_loc") and x.wild_loc == caller.wild_loc) or x.location == caller, list_)

        objs = caller.search(string, location=location, ignore_errors=True)

        if index == '.all':
            pass
        elif index == None:
            objs = objs[:n]
        else:
            try:
                objs = [objs[index]]
            except IndexError:
                objs = []

        return objs      

    def at_multimatch_input(self, ostring):
        """
        Parse number-identifiers.

        This parser will be called by the engine when a user supplies
        a search term. The search term must be analyzed to determine
        if the user wants to differentiate between multiple matches
        (usually found during a previous search).
        
        This method should separate out any identifiers from the search
        string used to differentiate between same-named objects. The
        result should be a tuple (index, search_string) where the index
        gives which match among multiple matches should be used (1 being
        the lowest number, rather than 0 as in Python).

        This parser version will identify search strings on the following
        forms

          object.2

        This will be parsed to (2, "object") and, if applicable, will tell
        the engine to pick the second from a list of same-named matches of
        objects called "object".
        Also supports
 
          objects.all

        to get all objects of the same name.

        Ex for use in a game session:

         > look
        You see: ball, ball, ball and ball.

         > get ball
         You get the ball.

         > get ball.3
         You get the ball.

         > get ball.all
         You get the ball.
         You get the ball.
         You get the ball.
         You get the ball.

        """
    
        if not isinstance(ostring, basestring):
            return (None, ostring)   
        index  = ostring.find('.')
        if index < 0:
            return (None, ostring)
        number = None
        # this is to deal with the .all suffix (ex. get sword.all)
        if ostring[index:] == ".all":
	    return (".all", ostring[:index])
        try:
            number = int(ostring[index+1:])-1
            return (number, ostring[:index])
        except ValueError:
            #not a number; this is not an identifier.
            return (None, ostring)
        except IndexError:
            return (None, ostring)



class MuxCommand(default_cmds.MuxCommand):
    """
    This sets up the basis for a Evennia's 'MUX-like' command
    style. The idea is that most other Mux-related commands should
    just inherit from this and don't have to implement parsing of
    their own unless they do something particularly advanced.

    A MUXCommand command understands the following possible syntax:

      name[ with several words][/switch[/switch..]] arg1[,arg2,...] [[=|,] arg[,..]]

    The 'name[ with several words]' part is already dealt with by the
    cmdhandler at this point, and stored in self.cmdname. The rest is stored
    in self.args.

    The MuxCommand parser breaks self.args into its constituents and stores them in the
    following variables:
      self.switches = optional list of /switches (without the /)
      self.raw = This is the raw argument input, including switches
      self.args = This is re-defined to be everything *except* the switches
      self.lhs = Everything to the left of = (lhs:'left-hand side'). If
                 no = is found, this is identical to self.args.
      self.rhs: Everything to the right of = (rhs:'right-hand side').
                If no '=' is found, this is None.
      self.lhslist - self.lhs split into a list by comma
      self.rhslist - list of self.rhs split into a list by comma
      self.arglist = list of space-separated args (including '=' if it exists)

      All args and list members are stripped of excess whitespace around the
      strings, but case is preserved.
      """

    def func(self):
        """
        This is the hook function that actually does all the work. It is called
        by the cmdhandler right after self.parser() finishes, and so has access
        to all the variables defined therein.
        """
        # this can be removed in your child class, it's just
        # printing the ingoing variables as a demo.
        super(MuxCommand, self).func()
